
#Copyright (C) 2011 Daniele Simonetti
#
#This program is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

import sys, time
from threading import Thread
### PySide ###
from PySide import QtCore, QtGui
### TVRAGE ###
from tvrage import feeds
from xml.etree.ElementTree import tostring
### QUEUE ###
from Queue import Queue
### Exceptions ###
from httplib import IncompleteRead
### To download image ###
import osutil

#HACK FOR TVRAGE ( new services )
feeds.BASE_URL = 'http://services.tvrage.com/feeds/%s.php?%s=%s'

### CACHE PROVIDER ###
class CacheProvider:
    def __init__(self):
        self.cache_shows = {}
        self.cache_eps = {}

    def add_show(self, info):
        self.cache_shows[info.showid] = info

    def add_eps(self, showid, eps):
        self.cache_eps[showid] = eps

    def get_show(self, showid):
        if showid in self.cache_shows:
            return self.cache_shows[showid]
        return None

    def get_eps(self, showid):
        if showid in self.cache_eps:
            return self.cache_eps[showid]
        return None

cache = CacheProvider()

########## TV RAGE PROVIDER THREAD CLASS ##########
class TvRageShowProvider(Thread):
  def __init__ (self, queue, target):
    Thread.__init__(self)
    self.queue = queue
    self.mutex = QtCore.QMutex(QtCore.QMutex.NonRecursive)
    self.target = target
    self.is_closing = False

  def set_closing(self):
    self.is_closing = True

  def run(self):
    while not self.queue.empty():      
      item = self.queue.get(True)

      if self.is_closing:
        self.queue.task_done()
        print 'thread is closing...'
        continue
      
      try:
        shows = feeds.search(item['show'])
      except Exception as tve:
        print tve
        self.queue.task_done()
        self.queue.put(item, True)
        continue
        
      got = min(5, len(shows))
      list = []
      for i in range(0, got):
          node = shows[i]
          si = ShowItem(node.find('showid').text)
          si.showname = node.find('name').text
          si.link = node.find('link').text
          si.country = node.find('country').text
          si.started = node.find('started').text
          si.ended = node.find('ended').text
          si.seasons = node.find('seasons').text
          si.status = node.find('status').text
          genres_nodes = node.find('genres')
          for g in genres_nodes:
            si.genres.append(g.text)
          list.append(si)
          cache.add_show(si)

      QtGui.qApp.postEvent(self.target, ShowProviderEvent(item, list))
      self.queue.task_done()
    #print 'TvRageShowProvider end'  

########## TV RAGE PROVIDER THREAD CLASS ##########
class TvRageShowInfoProvider(Thread):
  def __init__ (self, queue, target):
    Thread.__init__(self)
    self.queue = queue
    self.mutex = QtCore.QMutex(QtCore.QMutex.NonRecursive)
    self.target = target
    self.is_closing = False

  def set_closing(self):
    self.is_closing = True

  def run(self):
    while not self.queue.empty():      
      item = self.queue.get(True)

      if self.is_closing:
        self.queue.task_done()
        print 'thread is closing...'
        continue

      # CHECK CACHE FIRST
      showid = item['showid']
      si = cache.get_show(showid)
      if si is not None:
          if 'method' in item:
            if item['method'] == 'send':
                QtGui.qApp.sendEvent(self.target, ShowProviderEvent(item, [si]))
          QtGui.qApp.postEvent(self.target, ShowProviderEvent(item, [si]))

      try:    
        node = feeds.full_show_info(item['showid'])            
      except IncompleteRead:      
        self.queue.task_done()
        if not self.is_closing:
            self.queue.put(item, True)
        continue
      except Exception as tve:
        print tve
        self.queue.task_done()
        continue
      
      si = ShowItem(node.find('showid').text)
      try:
        si.showname = node.find('showname').text
      except:
        si.showname = node.find('name').text
      si.link = node.find('showlink').text
      si.country = node.find('origin_country').text
      si.started = node.find('started').text
      try:
        si.startdate = node.find('startdate').text
      except:
        si.startdate = node.find('started').text
      si.ended = node.find('ended').text
      try:
        si.seasons = node.find('seasons').text
      except:
        si.seasons = node.find('totalseasons').text
      si.runtime = node.find('runtime').text
      si.status = node.find('status').text
      try:
        si.image_link = node.find('image').text        
        if len(si.image_link) > 0:
            si.local_image = osutil.download_image(si.image_link,\
            osutil.get_user_data_path('image_cache'),\
            si.showid) or ''
      except Exception as e:
        print e
        si.image_link = ''
      genres_nodes = node.find('genres')
      for g in genres_nodes:
        si.genres.append(g.text)
      
      cache.add_show(si)

      if 'method' in item:
        if item['method'] == 'send':
            QtGui.qApp.sendEvent(self.target, ShowProviderEvent(item, [si]))
      QtGui.qApp.postEvent(self.target, ShowProviderEvent(item, [si]))
      self.queue.task_done()
    #print 'TvRageShowInfoProvider end'  

########## TV RAGE PROVIDER THREAD CLASS ##########
class TvRageEpisodeProvider(Thread):
  def __init__ (self, queue, target):
    Thread.__init__(self)
    self.queue = queue
    self.mutex = QtCore.QMutex(QtCore.QMutex.NonRecursive)
    self.target = target
    self.is_closing = False

  def set_closing(self):
    self.is_closing = True
    
  def run(self):    
    while not self.queue.empty():            
      item = self.queue.get(True)
      
      if self.is_closing:        
        self.queue.task_done()
        print 'thread is closing...'
        continue      
      
      showid = item['showid']
      
      # CHECK CACHE FIRST
      eps = cache.get_eps(showid)
      if eps is not None:
        epevent = EpisodesProviderEvent(item, eps)
        if 'method' in item:
            if item['method'] == 'send':                
                QtGui.qApp.sendEvent(self.target, epevent)
            QtGui.qApp.postEvent(self.target, epevent)
            return

      try:
        #eps = feeds.episode_list(showid, node='Episodelist')
        info = feeds.episode_list(showid)     
      except IncompleteRead:
        self.queue.task_done()
        if not self.is_closing:
            self.queue.put(item, True)
        continue
      except Exception as e:
        print e
        self.queue.task_done()
        #self.queue.put(item, True)        
        continue
        
      eps = info.find('Episodelist')
      showname = info.find('name').text

      list = []
      try:
        seasons = eps.findall('Season')
      except:
        seasons = []
        
      for season in seasons:
        epnodes = season.findall('episode')
        sn = season.get('no', 0)
        for epnode in epnodes:
            epitem = EpisodeItem()
            epitem.title = epnode.find('title').text
            epitem.seasonnum = epnode.find('seasonnum').text
            epitem.ep = epnode.find('epnum').text
            epitem.airdate = epnode.find('airdate').text
            epitem.link = epnode.find('link').text
            epitem.showid = showid
            epitem.showname = showname
            epitem.season = sn
            list.append(epitem)

      if len(list) > 0:
        cache.add_eps(showid, list)

      epevent = EpisodesProviderEvent(item, list)
      QtGui.qApp.postEvent(self.target, epevent)
      self.queue.task_done()
    #print 'TvRageEpisodeProvider end'

############# EVENT DISPATCH #############
showsEventType = QtCore.QEvent.Type(QtCore.QEvent.registerEventType())
epsEventType = QtCore.QEvent.Type(QtCore.QEvent.registerEventType())


class ShowProviderEvent(QtCore.QEvent):
  def __init__(self, source, shows):
    super(ShowProviderEvent, self).__init__(showsEventType)
    self.source = source
    self.shows=shows       

class EpisodesProviderEvent(QtCore.QEvent):
  def __init__(self, source, eps):
    super(EpisodesProviderEvent, self).__init__(epsEventType)
    self.source = source
    self.eps=eps


    
########## ITEM CLASSES ############    
class ShowItem:
    def __init__(self, id):      
      self.showid = id
      self.showname = ''
      self.link = ''
      self.country = ''
      self.started = ''
      self.ended = ''
      self.seasons = ''
      self.status = ''
      self.startdate = ''
      self.runtime = ''
      self.image_link = ''
      self.local_image = ''
      self.genres = []
         
    def __str__(self):
      return self.showname.encode('utf-8')
      
    def __unicode__(self):
        return self.showname
      
class EpisodeItem:
    def __init__(self):      
      self.title = ''
      self.seasonnum = ''
      self.showname = ''
      self.showid = ''
      self.airdate = ''
      self.link = ''
      self.ep = ''
      self.absep = ''
      self.season = ''
      
    def __str__(self):
      return '%sx%s - %s' % (self.season, self.seasonnum, self.title.encode('utf-8'))
    
    def __unicode__(self):
        return '%sx%s - %s' % (self.season, self.seasonnum, self.title)

